package com.cy;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.cy.service.ConsumerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.concurrent.atomic.AtomicLong;

/**
 * @Usefulness: Consumer启动类
 * @Author: LeiTing
 * @Date: 2021/9/15  14:14
 * @Version 1.0
 */

/**
 * 服务消费方对象的启动类
 * 业务描述：
 * 当客户端(浏览器，手机app)向服务消费方发起请求时，
 * 服务消费方调用服务提供方的api，进而获取服务提供方
 * 的数据。
 * 例如：
 * 我们访问一个订单模块数据(例如我的订单)，订单模块中
 * 还要呈现商品信息。
 */
@EnableFeignClients  //注解告诉SpringCloud启动Feign Starter
@SpringBootApplication
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }

    /**
     * 构建RestTemplate对象，并将此对象交给spring管理
     * 后续我们会通过此对象进行远程服务调用
     * @return
     */
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    @LoadBalanced
    @Bean
    public RestTemplate loadBalancerRestTemplate(){
        return new RestTemplate();
    }

    @RestController
    public class ConsumerController{

        //表明支持负载均衡远程调用
        /**
         * 负载均衡客户端对象
         */
        @Autowired
        private LoadBalancerClient loadBalancerClient;

        @Autowired
        private RestTemplate restTemplate;

        @Autowired
        private RestTemplate loadBalancerRestTemplate;

        @Value("${spring.application.name}")
        private String appName;

        @Autowired
        private ConsumerService consumerService;

        //url:http://localhost:8090/consumer/findById?id=10
        @GetMapping("/consumer/findById")
        @SentinelResource("res") //监控资源
        public String doFindByid(@RequestParam("id") Integer id){//写入@RequestParam("id")后必须传入参数 不然报错
            return "Resource id is "+id;
        }

        private AtomicLong along = new AtomicLong(1);
        //模拟慢调用
        //此函数用于测试降级处理
        //url:http://localhost:8090/consumer/doRestEcho1
        @GetMapping("/consumer/doRestEcho1")
        public String doRestEcho1() throws InterruptedException {
            long num = along.getAndIncrement();
            if(num%2==0)Thread.sleep(200);
            //调用服务提供方API(http://ip:port/path)
            //1.定义要调用的API
            String url="http://localhost:8081/provider/echo/"+appName;
            //2.谁去访问这个API restTemplate;
            return restTemplate
                    .getForObject(url, String.class );
        }


//        //url:http://localhost:8090/consumer/doRestEcho1
//        @GetMapping("/consumer/doRestEcho1")
//        public String doRestEcho1(){
//            consumerService.doGetResource();
//            //调用服务提供方API(http://ip:port/path)
//            //1.定义要调用的API
//            String url="http://localhost:8081/provider/echo/"+appName;
//            //2.谁去访问这个API restTemplate;
//            return restTemplate
//                    .getForObject(url, String.class );
//        }


        /**
         * 负载均衡方式调用
         * @return
         */
        //url:http://localhost:8090/consumer/doRestEcho2
        @GetMapping("/consumer/doRestEcho2")
        public String doRestEcho2(){
            //1.从注册中心获取服务实例
            ServiceInstance instance =
                    loadBalancerClient
                            .choose("sca-provider");
            //2.基于RestTemplate进行服务实例对象
            String ip = instance.getHost();//ip
            int port=instance.getPort();//port
           // String url="http://"+ip+":"+port+"/provider/echo/"+appName;
            String url=String.format("http://%s:%s/provider/echo/%s",ip,port,appName);
            return restTemplate.getForObject(url,String.class);
        }

        //url:http://localhost:8090/consumer/doRestEcho3
        //使用@LoadBalanced注解方法
        @GetMapping("/consumer/doRestEcho3")
        public String doRestEcho3() {
            String serviceId = "sca-provider";
            //定义url
            String url=
                    String.format("http://%s/provider/echo/%s", serviceId, appName);
            //服务调用
            return loadBalancerRestTemplate.getForObject(url,String.class );
        }

    }

}
